using System;
using System.Collections.Generic;
using System.Text;

namespace NCommet.Core
{
    /// <summary>
    /// RelItem defines the relation of two items.
    /// The relation is directed from one item, the subject (or owner), to the other, the object (or relative).
    /// </summary>
    [Serializable]
    public class RelItem
    {
        #region Fields and Properties

        private DateTime? dttm = null;

        private string relationType;

        /// <summary>
        /// The relation type is a user defined value that identifies the relationship.
        /// </summary>
        public string RelationType
        {
            get { return relationType; }
            set { relationType = value; }
        }

        private Item owner;

        /// <summary>
        /// The item that owns the relationship (the subject item).
        /// </summary>
        public Item Owner
        {
            get { return owner; }
            set { owner = value; }
        }

        private Item relative;

        /// <summary>
        /// The item that the relationship points to (the object item).
        /// </summary>
        public Item Relative
        {
            get { return relative; }
            set { relative = value; }
        }
        #endregion

        #region Equals & HashCode
        /// <summary>
        /// Checks for equality between RelItems. A relItem is equal to another when their
        /// owners, relatives and relation types are equal.
        /// </summary>
        /// <param name="obj">The object that is checked for equality against this relItem.</param>
        /// <returns>True, if the relItems are equal.</returns>
        public override bool Equals(object obj)
        {
            if (this == obj)
                return true;
            if (obj == null || !(obj is RelItem))
                return false;
            RelItem that = (RelItem)obj;
            return this.owner == that.owner && this.relative == that.relative && this.relationType == that.relationType;
        }

        /// <summary>
        /// Returns the hash code of this relItem.
        /// </summary>
        /// <returns>The hashcode of the relItem.</returns>
        public override int GetHashCode()
        {
            int result = 0;
            if (this.owner != null)
                result = this.owner.GetHashCode();
            if (this.relative != null)
                result = result * 11 + this.relative.GetHashCode();
            if (this.relationType != null)
                result = result * 13 + this.relationType.GetHashCode();
            return result;
        }
        #endregion

        /// <summary>
        /// Creates a new empty RelItem.
        /// </summary>
        protected RelItem()
        {
        }

        /// <summary>
        /// Creates a new transient RelItem and assigns all of its properties.
        /// </summary>
        /// <param name="owner">The item that participates as subject in the relation.</param>
        /// <param name="relative">The item that participates as object in the relation.</param>
        /// <param name="relationType">The relation of the two items.</param>
        protected internal RelItem(Item owner, Item relative, string relationType)
        {
            this.owner = owner;
            this.relative = relative;
            this.relationType = relationType;
        }

        /// <summary>
        /// Deletes this relItem from its owner's relatives collection.
        /// </summary>
        public void Delete()
        {
            owner.Relatives.Remove(this);
        }
    }
}
